home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir27 / calctool.zip / FUNCTION.C < prev    next >
C/C++ Source or Header  |  1992-09-09  |  19KB  |  631 lines

  1.  
  2. /*  @(#)functions.c 1.7 89/11/01
  3.  *
  4.  *  This file contains the seperate functions used by calctool,
  5.  *  whenever a calculator button is pressed.
  6.  *
  7.  *  Copyright (c) Rich Burridge.
  8.  *                Sun Microsystems, Australia - All rights reserved.
  9.  *
  10.  *  Basic algorithms, copyright (c) Ed Falk.
  11.  *                Sun Microsystems, Mountain View.
  12.  *
  13.  *  Permission is given to distribute these sources, as long as the
  14.  *  copyright messages are not removed, and no monies are exchanged.
  15.  *
  16.  *  No responsibility is taken for any errors or inaccuracies inherent
  17.  *  either to the comments or the code of this program, but if
  18.  *  reported to me then an attempt will be made to fix them.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <strings.h>
  24. #include <math.h>
  25. #include "calctool.h"
  26. #include "color.h"
  27. #include "extern.h"
  28.  
  29. extern double acos(), acosh(), asin(), asinh(), atan(), atanh() ;
  30. extern double cos(), cosh(), exp(), fabs(), log(), log10(), pow() ;
  31. extern double sin(), sinh(), sqrt(), tan(), tanh() ;
  32. extern double addition(), subtraction(), multiply(), division() ;
  33.  
  34. BOOLEAN ibool() ;
  35. double setbool() ;
  36.  
  37.  
  38. do_accuracy()     /* Set display accuracy. */
  39. {
  40.   if (current >= '0' && current <= '9')
  41.     {
  42.       accuracy = char_val(current) ;
  43.       make_registers() ;
  44.     }
  45. }
  46.  
  47.  
  48. do_base()    /* Change the current base setting. */
  49. {
  50.   switch (current)
  51.     {
  52.       case 'B' : base = BIN ;
  53.                  break ;
  54.       case 'O' : base = OCT ;
  55.                  break ;
  56.       case 'D' : base = DEC ;
  57.                  break ;
  58.       case 'H' : base = HEX ;
  59.     }
  60.   grey_buttons(base) ;
  61.   set_item(BASEITEM, base_str[(int) base]) ;
  62.   show_display(disp_val) ;
  63.   if (rstate) make_registers() ;
  64. }
  65.  
  66.  
  67. do_calculation()      /* Perform arithmetic calculation and display result. */
  68. {
  69.   if (current == '=' && old_cal_value == '=')
  70.     if (new_input) result = last_input ;
  71.     else disp_val = last_input ;
  72.  
  73.   if (current != '=' && old_cal_value == '=') cur_op = '?' ;
  74.   switch (cur_op)
  75.     {
  76.       case CCTRL('c') :                              /* cos. */
  77.       case CCTRL('s') :                              /* sin. */
  78.       case CCTRL('t') :                              /* tan. */
  79.       case '?'        : result = disp_val ;          /* Undefined. */
  80.                         break ;
  81.       case '+'        :                              /* Addition. */
  82.                         result = addition(result, disp_val) ;
  83.                         break ;
  84.       case '-'        :                              /* Subtraction. */
  85.                         result = subtraction(result, disp_val) ;
  86.                         break ;
  87.       case 'x'        :                              /* Multiplication. */
  88.                         result = multiply(result, disp_val) ;
  89.                         break ;
  90.       case '/'        :                              /* Division. */
  91.                         result = division(result, disp_val) ;
  92.                         break ;
  93.       case '%'        : result *= disp_val * 0.01 ;              /* % */
  94.                         break ;
  95.       case 'Y'        : result = pow(result, disp_val) ;         /* y^x */
  96.                         break ;
  97.       case '&'        : result = setbool(ibool(result) &         /* AND */
  98.                                          ibool(disp_val)) ;
  99.                         break ;
  100.       case '|'        : result = setbool(ibool(result) |         /* OR */
  101.                                          ibool(disp_val)) ;
  102.                         break ;
  103.       case '^'        : result = setbool(ibool(result) ^         /* XOR */
  104.                                          ibool(disp_val)) ;
  105.                         break ;
  106.       case 'n'        : result = setbool(~(ibool(result) ^       /* XNOR */
  107.                                            ibool(disp_val))) ;
  108.                         break ;
  109.       case '='        : break ;                                  /* Equals. */
  110.     }
  111.   show_display(result) ;
  112.   if (!(current == '=' && old_cal_value == '=')) last_input = disp_val ;
  113.  
  114.   disp_val = result ;
  115.   if (current != '=') cur_op = current ;
  116.   old_cal_value = current ;
  117.   new_input = key_exp = 0 ;
  118. }
  119.  
  120.  
  121. do_clear()       /* Clear the calculator display and re-initialise. */
  122. {
  123.   clear_display() ;
  124.   if (error) set_item(DISPLAYITEM, "") ;
  125.   initialise() ;
  126. }
  127.  
  128.  
  129. do_constant()
  130. {
  131.   if (current >= '0' && current <= '9')
  132.     {
  133.       disp_val = con_vals[char_val(current)] ;
  134.       show_display(disp_val) ;
  135.     }
  136. }
  137.  
  138.  
  139. do_delete()     /* Remove the last numeric character typed. */
  140. {
  141.   if (strlen(display)) display[strlen(display)-1] = '\0' ;
  142.  
  143. /*  If we were entering a scientific number, and we have backspaced over
  144.  *  the exponent sign, then this reverts to entering a fixed point number.
  145.  */
  146.  
  147.   if (key_exp && !(index(display, '+')))
  148.     {
  149.       key_exp = 0 ;
  150.       display[strlen(display)-1] = '\0' ;
  151.       set_item(OPITEM, "") ;
  152.     }
  153.  
  154.   set_item(DISPLAYITEM, display) ;
  155.   disp_val = convert_display() ;    /* Convert input to a number. */
  156. }
  157.  
  158.  
  159. do_exchange()         /* Exchange display with memory register. */
  160. {
  161.   double temp ;
  162.  
  163.   if (current >= '0' && current <= '9')
  164.     {
  165.       temp = disp_val ;
  166.       disp_val = mem_vals[char_val(current)] ;
  167.       mem_vals[char_val(current)] = temp ;
  168.       make_registers() ;
  169.     }
  170. }
  171.  
  172.  
  173. do_expno()           /* Get exponential number. */
  174. {
  175.   if (!new_input)
  176.     {
  177.       STRCPY(display, "1.0 +") ;
  178.       new_input = pointed = 1 ;
  179.       toclear = 0 ;
  180.     }
  181.   else if (!pointed)
  182.     {
  183.       STRNCAT(display, ". +", 3) ;
  184.       pointed = 1 ;
  185.     }
  186.   else if (!key_exp) STRNCAT(display, " +", 2) ;
  187.   key_exp = 1 ;
  188.   exp_posn = index(display, '+') ;
  189.   set_item(DISPLAYITEM, display) ;
  190.   disp_val = convert_display() ;       /* Convert input to a number. */
  191. }
  192.  
  193.  
  194. double
  195. do_factorial(val)     /* Calculate the factorial of val. */
  196. double val ;
  197. {
  198.   double a ;
  199.   int i ;
  200.  
  201.   a = val ;
  202.   if (val == (int) val && val > 0.0)   /* Only for positive integers. */
  203.     {
  204.       i = val ;
  205.       a = 1.0 ;
  206.       while (i > 0)
  207.         {
  208.           a = multiply(a, (float) i) ;
  209.           if (error) break ;
  210.           i-- ;
  211.         }
  212.     }
  213.   return (a) ;
  214. }
  215.  
  216.  
  217. do_function()      /* Perform a user defined function. */
  218. {
  219.   int fno, i, n ;
  220.  
  221.   pending = 0 ;
  222.   if (current >= '0' && current <= '9')
  223.     {
  224.       fno = char_val(current) ;
  225.       for (i = 0 ; i < strlen(fun_vals[fno]); i++)
  226.         for (n = 0; n < TITEMS; n++)
  227.           if (fun_vals[fno][i] == buttons[n].value)
  228.             {
  229.               process_item(n) ;
  230.               break ;
  231.             }
  232.     }
  233. }
  234.  
  235.  
  236. do_help()         /* Show online help facility. */
  237. {
  238.   char help_str[MAXLINE], nextline[MAXLINE], *p ;
  239.   int n, y ;
  240.  
  241.   if (pending_op == '?')                        /* HELP. */
  242.     {     
  243.       if (ishelp) ishelp++ ;
  244.       pending_op = '=' ;
  245.       make_canvas(0) ;
  246.       set_cursor(MAINCURSOR) ;
  247.     }     
  248.   else    
  249.     {
  250.       clear_canvas(KEYCANVAS, WHITE) ;
  251.       y = 20 ;
  252.       if (!ishelp)
  253.         drawtext(5, y, KEYCANVAS, NFONT, BLACK, "No help file found.") ;
  254.       else
  255.         {
  256.           for (n = 0; n < TITEMS; n++)
  257.             if (current == buttons[n].value) break ;
  258.           color = (iscolor) ? buttons[n].color : WHITE ;
  259.           clear_canvas(KEYCANVAS, color) ;
  260.           SPRINTF(help_str, "_%s_\n", buttons[n].str) ;
  261.           rewind(hfd) ;
  262.           y = 15 ;
  263.           p = fgets(nextline, BUFSIZ, hfd) ;
  264.           if (EQUAL(p, "_calctool.help_\n"))
  265.             {
  266.               while (p = fgets(nextline, BUFSIZ, hfd))
  267.                 if (*p == '_' && EQUAL(p, help_str)) break ;
  268.               if (!p) drawtext(5, y, KEYCANVAS, NFONT, BLACK,
  269.                                "No help for this item.") ;
  270.               for (;;)
  271.                 {
  272.                   FGETS(nextline, BUFSIZ, hfd) ;
  273.                   if (nextline[0] == '_') break ;
  274.                   nextline[strlen(nextline)-1] = '\0' ;
  275.                   drawtext(5, y, KEYCANVAS, NFONT, BLACK, nextline) ;
  276.                   y += 15 ;
  277.                 }
  278.             }    
  279.           else drawtext(5, y, KEYCANVAS, NFONT, BLACK,
  280.                         "Invalid help file given.") ;
  281.         }
  282.       drawtext(5, y+25, KEYCANVAS, NFONT, BLACK,
  283.                "Click LEFT or press any valid key.") ;
  284.       pending_op = '?' ;
  285.       return ;
  286.     }
  287. }
  288.  
  289.  
  290. do_immediate()
  291. {
  292.   switch (current)
  293.     {
  294.       case '[' : disp_val = setbool(ibool(disp_val)) ;          /* &32 */
  295.                  break ;
  296.       case ']' : disp_val = setbool(ibool(disp_val) & 0xffff) ; /* &16 */
  297.                  break ;
  298.       case '{' : disp_val = exp(disp_val) ;                     /* e^x */
  299.                  break ;
  300.       case '}' : disp_val = exp(LN10*disp_val) ;                /* 10^x */
  301.                  break ;
  302.       case 'N' : disp_val = log(disp_val) ;                     /* ln */
  303.                  break ;
  304.       case 'G' : disp_val = log10(disp_val) ;                   /* log */
  305.                  break ;
  306.       case 'S' : disp_val = sqrt(disp_val) ;                    /* SQRT */
  307.                  break ;
  308.       case '~' : disp_val = setbool(~ibool(disp_val)) ;         /* NOT */
  309.                  break ;
  310.       case 'R' : disp_val = division(1.0, disp_val) ;           /* 1/x */
  311.                  break ;
  312.       case '!' : disp_val = do_factorial(disp_val) ;            /* x! */
  313.                  break ;
  314.       case '@' : disp_val = multiply(disp_val, disp_val) ;      /* x^2 */
  315.                  break ;
  316.       case 'C' : if (key_exp)                                   /* CHS */
  317.                    {
  318.                      if (*exp_posn == '+') *exp_posn = '-' ;
  319.                      else                  *exp_posn = '+' ;
  320.                      set_item(DISPLAYITEM, display) ;
  321.                      disp_val = convert_display() ;
  322.                      key_exp = 0 ;
  323.                    }
  324.                  else disp_val = -disp_val ;
  325.     }
  326.   show_display(disp_val) ;
  327. }
  328.  
  329.  
  330. do_keys()      /* Display/undisplay the calctool key values. */
  331. {
  332.   make_canvas(1) ;
  333. }
  334.  
  335.  
  336. do_number()
  337. {
  338.   int n ;
  339.   static int maxvals[4] = {1, 7, 9, 15} ;
  340.  
  341.   n = current - '0' ;
  342.   if (base == HEX && current >= 'a' && current <= 'f')
  343.     n = current - 'a' + 10 ;
  344.   if (n > maxvals[(int) base]) return ;
  345.  
  346.   if (toclear)
  347.     {
  348.       SPRINTF(display, "%c", current) ;
  349.       toclear = 0 ;
  350.     }
  351.   else if (strlen(display) < disp_length[(int) base])
  352.     STRNCAT(display, ¤t, 1) ;
  353.   set_item(DISPLAYITEM, display) ;
  354.   disp_val = convert_display() ;    /* Convert input to a number. */
  355.   new_input = 1 ;
  356. }
  357.  
  358.  
  359. do_numtype()         /* Set number type (fixed or scientific). */
  360. {
  361.   int n ;
  362.  
  363.   if (dtype == FIX) dtype = SCI ;
  364.   else dtype = FIX ;
  365.   n = row*BCOLS*2 + column*2 + portion ;
  366.   STRCPY(buttons[n].str, (dtype == FIX) ? "SCI " : "FIX ") ;
  367.   set_item(NUMITEM, dtype_str[(int) dtype]) ;
  368.   draw_button(row, column, 0, NORMAL) ;
  369.   draw_button(row, column, 1, NORMAL) ;
  370.   show_display(disp_val) ;
  371. }
  372.  
  373.  
  374. do_pending()
  375. {
  376.   if (base != DEC) grey_buttons(DEC) ;    /* Reshow all the keys. */
  377.   switch (pending)
  378.     {
  379.       case '#'        : do_constant() ;                            /* CON */
  380.                         break ;
  381.       case CCTRL('e') : do_exchange() ;                            /* EXCH */
  382.                         break ;
  383.       case CCTRL('f') : do_function() ;                            /* FUN */
  384.                         break ;
  385.       case 's'        :                                            /* STO */
  386.       case 'r'        : do_sto_rcl() ;                             /* RCL */
  387.                         if (pending_op == '+' || pending_op == '-' ||
  388.                             pending_op == 'x' || pending_op == '/') return ;
  389.                         break ;
  390.       case '<'        :                                            /* < */
  391.       case '>'        : do_shift() ;                               /* > */
  392.                         break ;
  393.       case 'A'        : do_accuracy() ;                            /* ACC */
  394.                         break ;
  395.       case '?'        : do_help() ;                                /* ? */
  396.                         if (pending_op == '?') return ;
  397.                         break ;
  398.       default         : if (!pending)
  399.                           {
  400.                             pending = current ;
  401.                             pending_op = '=' ;
  402.                             if (pending == '?') set_cursor(HELPCURSOR) ;
  403.                             if (pending == '?' && (ishelp <= 1)) do_pending() ;
  404.                             return ;
  405.                           }
  406.     }
  407.   show_display(disp_val) ;
  408.   if (error) set_item(OPITEM, "CLR") ;
  409.   else set_item(OPITEM, "") ;
  410.   pending = 0 ;
  411.   grey_buttons(base) ;      /* Just show numeric keys for current base. */
  412. }
  413.  
  414.  
  415. do_point()                  /* Handle numeric point. */
  416. {
  417.   if (!pointed)
  418.     {
  419.       if (toclear)
  420.         {
  421.           STRCPY(display, ".") ;
  422.           toclear = 0 ;
  423.         }
  424.       else if (strlen(display) < disp_length[(int) base])
  425.         STRNCAT(display, ".", 1) ;
  426.       pointed = 1 ;
  427.     }
  428.   set_item(DISPLAYITEM, display) ;
  429.   disp_val = convert_display() ;    /* Convert input to a number. */
  430. }
  431.  
  432.  
  433. do_portion()
  434. {
  435.   switch (current)
  436.     {
  437.       case 'U' : disp_val = fabs(disp_val) ;       /* ABS. */
  438.                  break ;
  439.       case 'F' : disp_val -= (int) disp_val ;      /* FRAC. */
  440.                  break ;
  441.       case 'I' : disp_val = (int) disp_val ;       /* INT. */
  442.     }
  443.   show_display(disp_val) ;
  444. }
  445.  
  446.  
  447. do_set_mode()           /* Set or unset various calculator modes. */
  448. {
  449.   switch (current)
  450.     {
  451.       case CCTRL('d') :                                    /* DEG */
  452.       case CCTRL('g') :                                    /* GRAD */
  453.       case CCTRL('r') : do_trigtype() ;                    /* RAD */
  454.                         break ;
  455.       case 'h'        : hyperbolic = !hyperbolic ;         /* HYP */
  456.                         set_item(HYPITEM, (hyperbolic) ? "HYP " : "    ") ;
  457.                         break ;
  458.       case 'i'        : inverse = !inverse ;               /* INV */
  459.                         set_item(INVITEM, (inverse) ? "INV " : "    ") ;
  460.                         break ;
  461.       case CCTRL('n') : do_numtype() ;                     /* FIX/SCI */
  462.     }
  463.   if (rstate) make_registers() ;
  464. }
  465.  
  466.  
  467. do_shift()     /* Perform bitwise shift on display value. */
  468. {
  469.   int n, shift ;
  470.   BOOLEAN temp ;
  471.  
  472.   if (current >= '0' && current <= '9')
  473.     {
  474.       for (n = 0; n < TITEMS; n++)
  475.         if (current == buttons[n].value) break ;
  476.       shift = char_val(buttons[n].value) ;
  477.       temp = ibool(convert_display()) ;
  478.       switch (pending)
  479.         {
  480.           case '<' : temp = temp << shift ;
  481.                      break ;
  482.           case '>' : temp = temp >> shift ;
  483.         }
  484.       STRCPY(display, make_number(setbool(temp))) ;
  485.       disp_val = last_input = convert_display() ;
  486.     }
  487. }
  488.  
  489.  
  490. do_sto_rcl()     /* Save/restore value to/from memory register. */
  491. {
  492.   if (current >= '0' && current <= '9')
  493.     switch (pending)
  494.       {
  495.         case 'r' : disp_val = mem_vals[char_val(current)] ;
  496.                    break ;
  497.         case 's' : switch (pending_op)
  498.                      {
  499.                        case '+' : mem_vals[char_val(current)] += disp_val ;
  500.                                   break ;
  501.                        case '-' : mem_vals[char_val(current)] -= disp_val ;
  502.                                   break ;
  503.                        case 'x' : mem_vals[char_val(current)] *= disp_val ;
  504.                                   break ;
  505.                        case '/' : mem_vals[char_val(current)] /= disp_val ;
  506.                                   break ;
  507.                        default  : mem_vals[char_val(current)] = disp_val ;
  508.                      }  
  509.                    pending_op = 0 ;
  510.                    make_registers() ;
  511.       }                 
  512.   else if (current == '+' || current == '-' ||
  513.            current == 'x' || current == '/') pending_op = current ;
  514. }
  515.  
  516.  
  517. do_trig()         /* Perform all trigonometric functions. */
  518. {
  519.   double temp ;
  520.  
  521.   if (!inverse)
  522.     {
  523.            if (ttype == DEG)  temp = disp_val * PI / 180.0 ;
  524.       else if (ttype == GRAD) temp = disp_val * PI / 200.0 ;
  525.       else                    temp = disp_val ;
  526.  
  527.       if (!hyperbolic)
  528.         switch (current)
  529.           {
  530.             case CCTRL('c') : tresults[(int) RAD] = cos(temp) ;    /* cos */
  531.                               break ;
  532.             case CCTRL('s') : tresults[(int) RAD] = sin(temp) ;    /* sin */
  533.                               break ;
  534.             case CCTRL('t') : tresults[(int) RAD] = tan(temp) ;    /* tan */
  535.           }
  536.       else
  537.         switch (current)
  538.           {
  539.             case CCTRL('c') : tresults[(int) RAD] = cosh(temp) ;   /* cosh */
  540.                               break ;
  541.             case CCTRL('s') : tresults[(int) RAD] = sinh(temp) ;   /* sinh */
  542.                               break ;
  543.             case CCTRL('t') : tresults[(int) RAD] = tanh(temp) ;   /* tanh */
  544.           }
  545.  
  546.       tresults[(int) DEG]  = tresults[(int) RAD] ;
  547.       tresults[(int) GRAD] = tresults[(int) RAD] ;
  548.     }
  549.   else
  550.     {
  551.       if (!hyperbolic)
  552.         switch (current)
  553.           {
  554.             case CCTRL('c') : disp_val = acos(disp_val) ;     /* acos */
  555.                               break ;
  556.             case CCTRL('s') : disp_val = asin(disp_val) ;     /* asin */
  557.                               break ;
  558.             case CCTRL('t') : disp_val = atan(disp_val) ;     /* atan */
  559.           }
  560.       else
  561.         switch (current)
  562.           {
  563.             case CCTRL('c') : disp_val = acosh(disp_val) ;    /* acosh */
  564.                               break ;
  565.             case CCTRL('s') : disp_val = asinh(disp_val) ;    /* asinh */
  566.                               break ;
  567.             case CCTRL('t') : disp_val = atanh(disp_val) ;    /* atanh */
  568.           }
  569.  
  570.       tresults[(int) DEG]  = disp_val * 180.0 / PI ;
  571.       tresults[(int) GRAD] = disp_val * 200.0 / PI ;
  572.       tresults[(int) RAD]  = disp_val ;
  573.     }
  574.  
  575.   cur_op = current ;
  576.   show_display(tresults[(int) ttype]) ;
  577.   disp_val = tresults[(int) ttype] ;
  578. }
  579.  
  580.  
  581. do_trigtype()          /* Change the current trigonometric type. */
  582. {
  583.   switch (current)
  584.     {
  585.       case CCTRL('d') : ttype = DEG ;
  586.                         break ;
  587.       case CCTRL('g') : ttype = GRAD ;
  588.                         break ;
  589.       case CCTRL('r') : ttype = RAD ;
  590.     }
  591.   if (cur_op == CCTRL('c') || cur_op == CCTRL('s') || cur_op == CCTRL('t'))
  592.     {
  593.       disp_val = tresults[(int) ttype] ;
  594.       show_display(tresults[(int) ttype]) ;
  595.     }
  596.   set_item(TTYPEITEM, ttype_str[(int) ttype]) ;
  597. }
  598.  
  599.  
  600. BOOLEAN
  601. ibool(x)
  602. double x ;
  603. {
  604.   BOOLEAN p ;
  605.  
  606.   if (x > 68719476736.00) return(0) ;
  607.   else if (x < -68719476736.00) return(0) ;
  608.        else
  609.          {
  610.            while(x < 0.0) x += 4294967296.00 ;
  611.            while(x > 4294967296.00) x -= 4294967296.00 ;
  612.            p = x ;
  613.            return (p) ;
  614.          }
  615. }
  616.  
  617.  
  618. double
  619. setbool(p)
  620. BOOLEAN p ;
  621. {
  622.   BOOLEAN q ;
  623.   double val ;
  624.  
  625.   q = p & 0x80000000 ;
  626.   p &= 0x7fffffff ;
  627.   val = p ;
  628.   if (q) val += 2147483648.0 ;
  629.   return(val) ;
  630. }
  631.